package com.skyd.core.android.game;

import java.util.Date;

import com.skyd.core.vector.Vector2DF;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * 继承于SurfaceView，提供基本的游戏显示功能，如帧频控制、双线程更新
 * 
 * @author SkyD
 * 
 */
public abstract class GameView extends SurfaceView implements
		SurfaceHolder.Callback, IGameDisplayBase {

	SurfaceHolder holder;

	/**
	 * 初始值为true。 功能注释：指示是否为首次显示，在第一次surfaceCreated事件之后变为false
	 */
	private Boolean _IsFirstShow = true;

	/**
	 * 获取IsFirstShow。 功能注释：指示是否为首次显示，在第一次surfaceCreated事件之后变为false
	 * 
	 * @return 当前的Boolean类型的值
	 */
	public Boolean getIsFirstShow() {
		return _IsFirstShow;
	}

	/**
	 * 初始值为false。 功能注释：指示当前是否执行线程刷新操作
	 */
	private boolean _Runnable = false;

	/**
	 * 获取Runnable。 功能注释：指示当前是否执行线程刷新操作
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getRunnable() {
		return _Runnable;
	}

	/**
	 * 设置Runnable。 功能注释：指示当前是否执行线程刷新操作
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	public void setRunnable(boolean value) {
		_Runnable = value;
	}

	/**
	 * 设置Runnable为其默认值(false)。 功能注释：指示当前是否执行线程刷新操作
	 */
	public void setRunnableToDefault() {
		setRunnable(false);
	}

	/**
	 * 初始值为60。 功能注释：每秒显示帧数
	 */
	private int _FPS = 60;

	/**
	 * 获取FPS。 功能注释：每秒显示帧数
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPS() {
		return _FPS;
	}

	/**
	 * 设置FPS。(应当在复写surfaceCreated方法中执行此操作，在构造函数中执行此方法无效) 功能注释：每秒显示帧数
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPS(int value) {
		_FPS = value;
		updateFrameRate(value);
	}

	/**
	 * 设置FPS为其默认值(60)。 功能注释：每秒显示帧数
	 */
	public void setFPSToDefault() {
		setFPS(60);
	}

	/**
	 * 根据帧频更新帧速率值，此方法在帧频被修改时自动调用
	 * 
	 * @param FPS
	 *            帧频
	 */
	protected void updateFrameRate(int FPS) {
		frameRate = 1000 / FPS;
	}

	/**
	 * 帧速率
	 */
	int frameRate;

	/**
	 * 根据操作起始时间及当前时间计算剩余的可休息时间，以保证帧频稳定
	 * 
	 * @param beginTime
	 *            此帧中的操作起始时间
	 * @return 剩余应休眠的时间
	 */
	protected long calculateSleepTime(Date beginTime) {
		return Math.max(0, frameRate
				- (new Date().getTime() - beginTime.getTime()));
	}

	/**
	 * 构造函数
	 */
	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);

		holder = this.getHolder();
		holder.addCallback(this);
		this.setFPSToDefault();
	}

	UpdateThread uThread;
	PaintThread pThread;

	/**
	 * 初始值为false。 功能注释：指示是否初始化完毕
	 */
	private Boolean _IsInitialized = false;

	/**
	 * 获取IsInitialized。 功能注释：指示是否初始化完毕
	 * 
	 * @return 当前的Boolean类型的值
	 */
	public Boolean getIsInitialized() {
		return _IsInitialized;
	}

	/**
	 * 设置IsInitialized。 功能注释：指示是否初始化完毕
	 * 
	 * @param value
	 *            要设置的Boolean类型值
	 */
	public void setIsInitialized(Boolean value) {
		_IsInitialized = value;
	}

	/**
	 * 设置IsInitialized为其默认值(false)。 功能注释：指示是否初始化完毕
	 */
	public void setIsInitializedToDefault() {
		setIsInitialized(false);
	}

	/**
	 * 初始化方法，在此方法中完成游戏初始化操作，如设置帧频、加载游戏对象
	 * 
	 * @param isFirstShow
	 *            指示是否为第一次显示屏幕，如果为false则表示此次初始化是从其他程序切回时发生的
	 */
	public abstract void init(Boolean isFirstShow);

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		uThread = new UpdateThread();
		pThread = new PaintThread();
		this.setRunnable(true);
		uThread.start();
		pThread.start();

		init(_IsFirstShow);
		_IsFirstShow = false;
		setIsInitialized(true);
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		this.setRunnable(false);
		setIsInitialized(false);
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {

	}

	/**
	 * 用于更新数据的线程
	 * 
	 * @author SkyD
	 * 
	 */
	class UpdateThread extends Thread {

		/**
		 * 用于存放每帧的起始时间
		 */
		Date beginTime;

		@Override
		public void run() {

			while (GameView.this._Runnable) {
				beginTime = new Date();
				GameView.this.UpdateInThread();
				try {
					Thread.sleep(GameView.this.calculateSleepTime(beginTime));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 用于绘图的线程
	 * 
	 * @author SkyD
	 * 
	 */
	class PaintThread extends Thread {
		/**
		 * 用于存放每帧的起始时间
		 */
		Date beginTime;

		@Override
		public void run() {

			while (GameView.this._Runnable) {
				beginTime = new Date();

				Canvas c = null;
//				try {
					c = getCanvas(holder);
					GameView.this.PaintInThread(c);
					if (_IsShowFPS) {
						GameView.this.processingFPS(c,beginTime);
					}
//				} finally {
					if (c != null)
						holder.unlockCanvasAndPost(c);
//				}

				try {
					Thread.sleep(GameView.this.calculateSleepTime(beginTime));
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 更新数据函数，用于在独立线程中执行更新数据操作
	 */
	protected abstract void UpdateInThread();
	
	/**
	 * 在需要获取SurfaceView的画布时被调用，子类可以重写此方法以仅获取部分画布，实现局部刷新
	 * @param holder holder
	 * @return 画布
	 */
	public Canvas getCanvas(SurfaceHolder holder) {
		return holder.lockCanvas();
	}

	/**
	 * 重绘方法，用于在独立线程中执行绘图操作
	 */
	protected abstract void PaintInThread(Canvas c);
	
	/**
	 * 用于FPS统计
	 */
	long fpsstart;
	/**
	 * 用于FPS统计
	 */
	int fpscount = 0;
	int fps;

	public void processingFPS(Canvas c, Date beginTime) {
		if (fpscount == 0)
			fpsstart = beginTime.getTime();

		fpscount++;

		if (beginTime.getTime() - fpsstart > 1000) {
			fps = fpscount - 1;
			fpscount = 0;
		}

		Paint paint = new Paint();
		paint.setColor(getFPSDrawColor());
		paint.setTextSize(getFPSDrawTextSize());
		c.drawText("FPS:" + fps, getFPSDrawPosition().getX(),
				getFPSDrawPosition().getY(), paint);
	}

	/**
	 * 初始值为false。 功能注释：指示是否显示帧频
	 */
	private boolean _IsShowFPS = false;

	/**
	 * 获取IsShowFPS。 功能注释：指示是否显示帧频
	 * 
	 * @return 当前的boolean类型的值
	 */
	public boolean getIsShowFPS() {
		return _IsShowFPS;
	}

	/**
	 * 设置IsShowFPS。 功能注释：指示是否显示帧频
	 * 
	 * @param value
	 *            要设置的boolean类型值
	 */
	private void setIsShowFPS(boolean value) {
		_IsShowFPS = value;
	}

	/**
	 * 显示FPS
	 * 
	 * @param x
	 *            X坐标
	 * @param y
	 *            Y坐标
	 * @param size
	 *            文字大小
	 * @param color
	 *            颜色
	 */
	public void showFPS(int x, int y, int size, int color) {
		setFPSDrawTextSize(size);
		setFPSDrawColor(color);
		showFPS(x, y);
	}

	/**
	 * 显示FPS
	 * 
	 * @param x
	 *            X坐标
	 * @param y
	 *            Y坐标
	 */
	public void showFPS(int x, int y) {
		getFPSDrawPosition().reset(x, y);
		showFPS();
	}

	/**
	 * 显示FPS
	 */
	public void showFPS() {
		setIsShowFPS(true);
	}

	/**
	 * 隐藏FPS
	 */
	public void hideFPS() {
		setIsShowFPS(false);
	}

	/**
	 * 初始值为new Vector2DF(10,10)。 功能注释：FPS绘制位置
	 */
	private Vector2DF _FPSDrawPosition = new Vector2DF(10, 10);

	/**
	 * 获取FPSDrawPosition。 功能注释：FPS绘制位置
	 * 
	 * @return 当前的Vector2DF类型的值
	 */
	public Vector2DF getFPSDrawPosition() {
		return _FPSDrawPosition;
	}

	/**
	 * 初始值为22。 功能注释：FPS绘制字体尺寸
	 */
	private int _FPSDrawTextSize = 22;

	/**
	 * 获取FPSDrawTextSize。 功能注释：FPS绘制字体尺寸
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPSDrawTextSize() {
		return _FPSDrawTextSize;
	}

	/**
	 * 设置FPSDrawTextSize。 功能注释：FPS绘制字体尺寸
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPSDrawTextSize(int value) {
		_FPSDrawTextSize = value;
	}

	/**
	 * 设置FPSDrawTextSize为其默认值(22)。 功能注释：FPS绘制字体尺寸
	 */
	public void setFPSDrawTextSizeToDefault() {
		setFPSDrawTextSize(22);
	}

	/**
	 * 初始值为Color.RED。 功能注释：FPS绘制颜色
	 */
	private int _FPSDrawColor = Color.RED;

	/**
	 * 获取FPSDrawColor。 功能注释：FPS绘制颜色
	 * 
	 * @return 当前的int类型的值
	 */
	public int getFPSDrawColor() {
		return _FPSDrawColor;
	}

	/**
	 * 设置FPSDrawColor。 功能注释：FPS绘制颜色
	 * 
	 * @param value
	 *            要设置的int类型值
	 */
	public void setFPSDrawColor(int value) {
		_FPSDrawColor = value;
	}

	/**
	 * 设置FPSDrawColor为其默认值(Color.RED)。 功能注释：FPS绘制颜色
	 */
	public void setFPSDrawColorToDefault() {
		setFPSDrawColor(Color.RED);
	}
}
